﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine.Unity;

public enum UnitAnimState
{
    Idle,
    Move,
    Attack,
    Die,
}
public class UnitAnimation : MonoBehaviour
{
    Animation m_UnityAnimation;
    SkeletonAnimation m_SkeletonAnimation;
    MeshRenderer m_MeshRenderer;
    UnitDisplay m_UnitDisplay;

    public Material m_NormalMaterial;
    public Material m_OutlineMaterial;

    public UnitAnimState m_CurrentState;
    public string m_SpineIdleName;
    public string m_SpineMoveName;
    public float m_MoveAnimScale = 1f;
    public string m_SpineAttackName;
    public float m_AttackAnimScale = 1f;
    public string m_SpineDieName;
    public float m_DieAnimScale = 1f;

    public float m_MoveDuration = 1f;
    public float m_AttackDuration = 1f;
    public float m_DieDuration = 1f;

    Vector3 m_StartPos;
    Vector3 m_TargetPos;
    float m_StateClock;
    bool m_Outline;

    // Start is called before the first frame update
    void Awake()
    {
        m_UnitDisplay = GetComponent<UnitDisplay>();
        m_UnityAnimation = GetComponent<Animation>();
        m_SkeletonAnimation = GetComponentInChildren<SkeletonAnimation>();
        m_MeshRenderer = GetComponentInChildren<MeshRenderer>();
        Idle();
    }

    // Update is called once per frame
    void Update()
    {
        m_MeshRenderer.transform.rotation = MyInputSystem.Instance.mainCameraTrans.rotation;

        m_StateClock += Time.deltaTime;
        switch (m_CurrentState)
        {
            case UnitAnimState.Move:
                if (m_StateClock > m_MoveDuration)
                {
                    transform.position = m_TargetPos;
                    m_UnitDisplay.OnMoveEnd();
                    Idle();
                }
                else
                {
                    transform.position = Vector3.Lerp(m_StartPos, m_TargetPos, m_StateClock / m_MoveDuration);
                }
                break;
            case UnitAnimState.Attack:
                if (m_StateClock > m_AttackDuration)
                {
                    m_UnitDisplay.OnAttack();
                    Idle();
                }
                break;
            case UnitAnimState.Die:
                if (m_StateClock > m_DieDuration)
                {
                    m_UnitDisplay.OnDieEnd();
                }
                break;
        }
    }
    public void SetCurrentActionHighlight(bool highlight)
    {
        if (highlight)
        {
            m_UnityAnimation.Play("current_display");
        }
        else
        {
            m_UnityAnimation.Play("normal");
        }
    }
    public void SetOutline(bool outline, Color color)
    {
        m_Outline = outline;
        if (outline)
        {
            m_MeshRenderer.material = m_OutlineMaterial;
            m_MeshRenderer.material.SetColor("_OutlineColor", color);
        }
        else
        {
            m_MeshRenderer.material = m_NormalMaterial;
        }
    }
    public void Idle()
    {
        m_StateClock = 0f;
        m_CurrentState = UnitAnimState.Idle;
        string currentAnim = "";
        var track = m_SkeletonAnimation.AnimationState.GetCurrent(0);
        if (track != null)
        {
            currentAnim = track.Animation.Name;
        }
        if (!currentAnim.Equals(m_SpineIdleName))
        {
            m_SkeletonAnimation.state.SetAnimation(0, m_SpineIdleName, true);
            m_SkeletonAnimation.state.TimeScale = 1f;
        }
    }
    public void Move(Vector3 targetPos)
    {
        m_StateClock = 0f;
        m_CurrentState = UnitAnimState.Move;
        FaceDirection(targetPos);
        m_StartPos = transform.position;
        m_TargetPos = targetPos;
        string currentAnim = "";
        var track = m_SkeletonAnimation.state.GetCurrent(0);
        if (track != null)
        {
            currentAnim = track.Animation.Name;
        }
        if (!currentAnim.Equals(m_SpineMoveName))
        {
            m_SkeletonAnimation.state.SetAnimation(0, m_SpineMoveName, true);
            m_SkeletonAnimation.state.TimeScale = m_MoveAnimScale;
        }
    }
    public void Hurt()
    {
        m_UnityAnimation.Play("hurt");
    }
    public void Attack(Vector3 target)
    {
        m_StateClock = 0f;
        m_CurrentState = UnitAnimState.Attack;
        FaceDirection(target);
        string currentAnim = "";
        var track = m_SkeletonAnimation.state.GetCurrent(0);
        if (track != null)
        {
            currentAnim = track.Animation.Name;
        }
        if (!currentAnim.Equals(m_SpineAttackName))
        {
            m_SkeletonAnimation.state.SetAnimation(0, m_SpineAttackName, true);
            m_SkeletonAnimation.state.TimeScale = m_AttackAnimScale;
        }
    }
    public void FaceDirection(Vector3 target)
    {
        Vector3 dir = target - transform.position;
        if (dir.x < -0.2f)
        {
            transform.localScale = new Vector3(-1f, 1f, 1f);
        }
        else if (dir.x > 0.2f)
        {
            transform.localScale = new Vector3(1f, 1f, 1f);
        }
    }
    public void Die()
    {
        m_StateClock = 0f;
        m_CurrentState = UnitAnimState.Die;
        string currentAnim = "";
        var track = m_SkeletonAnimation.state.GetCurrent(0);
        if (track != null)
        {
            currentAnim = track.Animation.Name;
        }
        if (!currentAnim.Equals(m_SpineDieName))
        {
            m_SkeletonAnimation.state.SetAnimation(0, m_SpineDieName, true);
            m_SkeletonAnimation.state.TimeScale = m_DieAnimScale;
        }
        m_UnityAnimation.Play("die");
    }
}
